using System;
using System.Collections.Generic;
using System.Threading;
using FluentAssertions;

namespace TripleA.StoryQ
{
    public abstract class BddTestDomain : IDisposable
    {
        protected Exception _expectedException;
        protected List<string> _timeline;

        protected BddTestDomain()
        {
            _timeline = new List<string>();
        }

        public virtual void Dispose()
        {
            DisplayTimeline();
        }

        public void SafeExecute(Action action)
        {
            try
            {
                action.Invoke();
            }
            catch (Exception ex)
            {
                _expectedException = ex;
            }
        }

        public void SimulateBackgroundEvent(Action action, int interval, Action asyncAction)
        {
            var bgThread = new Thread((() =>
            {
                Thread.Sleep(interval);
                asyncAction.Invoke();
            }));
            bgThread.Start();
            action.Invoke();
        }

        public void ThrewNoException()
        {
            _expectedException.Should().BeNull();
        }

        public void ShouldThrow_Exception(Type expected)
        {
            _expectedException.Should().NotBeNull();
            _expectedException.Should().Match<Exception>(ee => ee.GetType() == expected);
        }

        public void _ShouldBeInTheExceptionMesssage(string content)
        {
            _expectedException.Message.Should().Contain(content);
        }

        public virtual void RecordEvent(string format, params object[] args)
        {
            _timeline.Add(string.Format("{0} {1}", DateTime.Now, string.Format(format, args)));
        }

        public virtual void DisplayTimeline()
        {
            Console.WriteLine("Events Timeline...");

            _timeline.ForEach(msg => Console.WriteLine("{0}", msg));
        }
    }
}